from py2neo import Node, Relationship, NodeMatcher

from src.database.connection import Neo4jInstance
from src.ifc.rule.task_type import *

# 若柱、梁、楼板的混凝土型号一致，可以在梁、楼板钢筋绑扎后，柱、梁、楼板混凝土一起施工
# 不知道混凝土型号，不考虑了


# 梁、楼板模板安装 FOLLOW 柱模板安装
# 虚拟节点，在多个前置节点后后置节点中间建立一个虚拟的，减少多对多的关系建立
def beam_slab_boarding_follow_column_boarding(storeys):
    for index, storey in enumerate(storeys):
        tx = Neo4jInstance.get_connect().begin()
        col_task_summary_node = Node(
            VirtualColumnBoardingSummary,
            Name="柱模板安装-汇总",
            Layer=storey["Name"],
        )
        tx.create(col_task_summary_node)

        col_boarding_tasks = tx.run(
            """
            MATCH (c:TaskColumnBoard {Layer:$Layer}) 
            RETURN c
        """,
            Layer=storey["Name"],
        ).data()
        col_boarding_tasks = [component["c"] for component in col_boarding_tasks]
        if len(col_boarding_tasks) > 0:
            for task in col_boarding_tasks:
                rel_boarding = Relationship(col_task_summary_node, "FOLLOW", task)
                tx.create(rel_boarding)

        # 梁、楼板模板-汇总
        beam_slab_task_summary_node = Node(
            VirtualBeamSlabBoardingSummary,
            Name="梁、楼板模板-汇总",
            Layer=storey["Name"],
        )
        tx.create(beam_slab_task_summary_node)
        rel_summary = Relationship(
            beam_slab_task_summary_node, "FOLLOW", col_task_summary_node
        )
        tx.create(rel_summary)

        beam_slab_boarding_tasks = tx.run(
            """
            MATCH (c {Layer:$Layer})
            WHERE c:TaskBeamBoard OR c:TaskSlabBoard
            RETURN c
        """,
            Layer=storey["Name"],
        ).data()
        beam_slab_boarding_tasks = [
            beam_slab_boarding_task["c"]
            for beam_slab_boarding_task in beam_slab_boarding_tasks
        ]

        for task in beam_slab_boarding_tasks:
            rel_boarding = Relationship(task, "FOLLOW", beam_slab_task_summary_node)
            tx.create(rel_boarding)
        tx.commit()


# 柱水泥浇灌 FOLLOW  梁、楼板模板安装
def column_concrete_follow_beam_slab_boarding(storeys):
    for index, storey in enumerate(storeys):
        tx = Neo4jInstance.get_connect().begin()
        col_task_summary_node = Node(
            VirtualColumnConcreteSummary, name="柱混凝土-汇总", Layer=storey["Name"]
        )

        col_concrete_tasks = tx.run(
            """
            MATCH (c:TaskColumnConcrete {Layer:$Layer}) 
            RETURN c
        """,
            Layer=storey["Name"],
        ).data()
        col_concrete_tasks = [component["c"] for component in col_concrete_tasks]
        for task in col_concrete_tasks:
            rel_boarding = Relationship(col_task_summary_node, "FOLLOW", task)
            tx.create(rel_boarding)

        beam_slab_summary_node = (
            NodeMatcher(tx)
            .match(VirtualBeamSlabBoardingSummary)
            .where(Layer=storey["Name"])
            .first()
        )
        rel = Relationship(col_task_summary_node, "FOLLOW", beam_slab_summary_node)
        tx.create(rel)
        tx.commit()


# 下个楼层开工，依赖前一个楼层的养护
def maintain(storeys):
    for index, storey in enumerate(storeys):
        tx = Neo4jInstance.get_connect().begin()
        # 养护-汇总
        maintain_task_summary_node = Node(
            VirtualMaintainSummary,
            Name="养护-汇总",
            Layer=storey["Name"],
        )
        tx.create(maintain_task_summary_node)
        # 所有 养护-汇总  FOLLOW依赖  构建养护
        main_tasks = tx.run(
            """
            MATCH (c {Layer:$Layer}) 
            WHERE c:TaskColumnMaintain OR c:TaskBeamMaintain OR c:TaskSlabMaintain
            RETURN c
        """,
            Layer=storey["Name"],
        ).data()
        main_tasks = [component["c"] for component in main_tasks]
        for main_task in main_tasks:
            rel_summary = Relationship(maintain_task_summary_node, "FOLLOW", main_task)
            tx.create(rel_summary)

        # 下一个楼层依赖当前楼层的养护
        if index < len(storeys) - 2:
            tx.run(
                """
            MATCH (parent),(child {GlobalId: $child_id})
            WHERE id(parent) = $parent_id
            MERGE (parent)<-[:FOLLOW]-(child)
            """,
                parent_id=maintain_task_summary_node.identity,
                child_id=storeys[index + 1]["GlobalId"],
            )
        tx.commit()
